﻿using System;
using System.Collections.Generic;
using System.Xml;
using Vaffanculo.Common.Constants;
using Vaffanculo.Migration.SchemaMigration;

namespace Vaffanculo.Migration.ImplementsSchema.Excel
{
    public class XmlMigration : ISchemaXmlMigration
    {
        public string PathXml{get; set; }

        public List<ISchemaFile> FilesSourceMigration { get; set; }

        private SChemaFile _sChemaFile;


        public void ReadMapXml()
        {
            

            FilesSourceMigration = new List<ISchemaFile>();
            _sChemaFile = new SChemaFile();
            
            var xmlDocument = new XmlDocument();
            xmlDocument.Load(PathXml);

            ReadSource(xmlDocument.GetElementsByTagName("Source"));
           /* foreach (XmlAttribute xmlAttribute in xmlNode.Attributes)
            {
                
            }*/

            XmlNodeList nodeListDimentions =  xmlDocument.GetElementsByTagName("Dimentions");
            foreach (XmlNode xmlNode in nodeListDimentions)
            {
                foreach (XmlNode childNode in xmlNode.ChildNodes)
                {
                    switch (childNode.Name)
                    {
                        case "Rows":
                            ReadRow(childNode.ChildNodes,MigrationConstants.Dimention);
                            break;
                        case "Columns":
                            ReadColumm(childNode.ChildNodes, MigrationConstants.Dimention);
                            break;
                        case "Constants":
                            ReadConstant(childNode.ChildNodes, false);
                            break;
                    }    
                }
                
            }

            nodeListDimentions = xmlDocument.GetElementsByTagName("Facts");
            foreach (XmlNode xmlNode in nodeListDimentions)
            {
                foreach (XmlNode childNode in xmlNode.ChildNodes)
                {
                    switch (childNode.Name)
                    {
                        case "Rows":
                            ReadRow(childNode.ChildNodes, MigrationConstants.Fact);
                            break;
                        case "Columns":
                            ReadColumm(childNode.ChildNodes, MigrationConstants.Fact);
                            break;
                        case "Intersections":
                            ReadIntersection(childNode.ChildNodes, MigrationConstants.Fact);
                            break;
                    }
                }

            }

            //ReadRow(xmlDocument.GetElementsByTagName("Rows"));
            //ReadColumm(xmlDocument.GetElementsByTagName("Columns"));

            FilesSourceMigration.Add(_sChemaFile);

        }


        private void ReadSource(XmlNodeList xmlnodeList)
        {
            _sChemaFile.Sheet = string.Empty;
            foreach (XmlNode xmlNode in xmlnodeList)
            {
                switch (xmlNode.Name)
                {
                    case "Source":
                        foreach (XmlNode childNode in xmlNode.ChildNodes)
                        {
                            switch (childNode.Name)
                            {
                                case "InputFiles":
                                    if (childNode.Attributes != null)
                                        foreach (XmlAttribute xmlAttribute in childNode.Attributes)
                                        {
                                            switch (xmlAttribute.Name)
                                            {
                                                case "fromdate":
                                                    _sChemaFile.DateTimeStart = DateTime.Parse(xmlAttribute.Value);
                                                    break;
                                                case "todate":
                                                    _sChemaFile.DateTimeEnd = DateTime.Parse(xmlAttribute.Value);
                                                    break;
                                            }   
                                        }
                                    foreach (XmlNode node in childNode.ChildNodes)
                                    {
                                        switch (node.Name)
                                        {
                                            case "Cycle":
                                                _sChemaFile.Cycle = node.InnerText;
                                                break;
                                            case "RootDir":
                                                _sChemaFile.PathFile = node.InnerText;
                                                break;
                                            case "FilePattern":
                                                _sChemaFile.FilePattern = node.InnerText;
                                                break;
                                            case "Sheet":
                                                _sChemaFile.Sheet = node.InnerText;
                                                break;
                                        }
                                    }
                                    break;
                            }
                        }

                        break;
                        
                }
                
            }
            
        }



        private void ReadConstant(XmlNodeList xmlnodes, bool isFact)
        {

            foreach (XmlNode xmlNode in xmlnodes)
            {
                if(isFact)
                {
                    var schemaFactExcel = new SchemaFactExcel { TypeFact = MigrationConstants.TypeMigrationConstant };
                    ReadFact(xmlNode, schemaFactExcel);
                    _sChemaFile.Facts.Add(schemaFactExcel);
                    
                }
                else
                {
                    var schemaDimentionExcel = new SChemaDimentionExcel{TypeDimention =MigrationConstants.TypeMigrationConstant};
                    ReadDimention(xmlNode, schemaDimentionExcel);
                    _sChemaFile.Dimentions.Add(schemaDimentionExcel);
                }
            }

        }


        private void ReadIntersection(XmlNodeList xmlnodes, string typerow)
        {

            foreach (XmlNode xmlNode in xmlnodes)
            {
                if (typerow == MigrationConstants.Dimention)
                {
                    var schemaDimentionExcel = new SChemaDimentionExcel
                    {
                        TypeDimention =
                            MigrationConstants.TypeMigrationIntersection
                    };
                    ReadDimention(xmlNode, schemaDimentionExcel);
                    _sChemaFile.Dimentions.Add(schemaDimentionExcel);
                }
                else
                {
                    var schemaFactExcel = new SchemaFactExcel { TypeFact = MigrationConstants.TypeMigrationIntersection };
                    ReadFact(xmlNode, schemaFactExcel);
                    _sChemaFile.Facts.Add(schemaFactExcel);
                }
            }

        }

        private void ReadRow(XmlNodeList xmlnodes, string typerow)
        {

            foreach (XmlNode xmlNode in xmlnodes)
            {
                if (typerow == MigrationConstants.Dimention)
                {
                    var schemaDimentionExcel = new SChemaDimentionExcel
                                                   {
                                                       TypeDimention =
                                                           MigrationConstants.TypeMigrationRow
                                                   };
                    ReadDimention(xmlNode, schemaDimentionExcel);
                    _sChemaFile.Dimentions.Add(schemaDimentionExcel);
                }
                else
                {
                    var schemaFactExcel = new SchemaFactExcel {TypeFact = MigrationConstants.TypeMigrationRow};
                    ReadFact(xmlNode,schemaFactExcel);
                    _sChemaFile.Facts.Add(schemaFactExcel);
                }
            }
            
        }

        private void ReadColumm(XmlNodeList xmlnodes, string typerow)
        {
            foreach (XmlNode xmlNode in xmlnodes)
            {
                if (typerow == MigrationConstants.Dimention)
                {
                    var schemaDimentionExcel = new SChemaDimentionExcel
                                                   {
                                                       TypeDimention =MigrationConstants.TypeMigrationColumm
                                                   };
                    ReadDimention(xmlNode, schemaDimentionExcel);
                    _sChemaFile.Dimentions.Add(schemaDimentionExcel);
                }
                else
                {
                    var schemaFactExcel = new SchemaFactExcel { TypeFact = MigrationConstants.TypeMigrationColumm };
                    ReadFact(xmlNode, schemaFactExcel);
                    _sChemaFile.Facts.Add(schemaFactExcel);
                    
                }

            }

        }

        private static void ReadFact(XmlNode xmlnode, ISchemaFact schemaFact)
        {
            foreach (XmlNode childNode in xmlnode.ChildNodes)
            {
                string var = childNode.Name;
                switch (var)
                {
                    case "Init":
                        if (childNode.Attributes != null)
                            foreach (XmlAttribute atrribute in childNode.Attributes)
                            {
                                switch (atrribute.Name)
                                {
                                    case "startwith":
                                        schemaFact.StartWith = atrribute.Value;
                                        break;
                                    case "searchInit":
                                        schemaFact.SearchInit = atrribute.Value;
                                        break;
                                    case "name":
                                        schemaFact.Name = atrribute.Value;
                                        break;
                                }

                            }
                        break;
                    case "Table":
                        if (childNode.Attributes != null)
                            foreach (XmlAttribute attribute in childNode.Attributes)
                            {
                                switch (attribute.Name)
                                {
                                    case "name":
                                        schemaFact.TableName = attribute.Value;
                                        break;
                                    case "fact":
                                        schemaFact.FactName = attribute.Value;
                                        break;
                                }

                            }
                        break;
                    case "Crossings":
                        schemaFact.Crossings = new List<ISchemaCross>();
                        foreach (XmlNode xmlNode in childNode.ChildNodes)
                        {
                            var schemaCrossExcel = new SchemaCrossExcel();
                            if (xmlNode.Attributes != null)
                            {
                                foreach (XmlAttribute xmlAttribute in xmlNode.Attributes)
                                {
                                    switch (xmlAttribute.Name)
                                    {
                                        case "namedimention":
                                            schemaCrossExcel.NameDimention = xmlAttribute.Value;
                                            break;
                                    }
                                }
                            }
                            schemaFact.Crossings.Add(schemaCrossExcel);
                                
                        }
                        break;
                    case "Composite":
                        var sChemaCompositeExcel = new SChemaCompositeExcel();
                        if (childNode.Attributes != null)
                            foreach (XmlAttribute attribute in childNode.Attributes)
                            {
                                switch (attribute.Name)
                                {
                                    case "composite":
                                        sChemaCompositeExcel.Composite = attribute.Value;
                                        break;
                                    case "name":
                                        sChemaCompositeExcel.Name = attribute.Value;
                                        break;
                                    case "srchname":
                                        sChemaCompositeExcel.SrchName = attribute.Value;
                                        break;

                                }

                            }
                        schemaFact.Composite = sChemaCompositeExcel;
                        break;
                }

            }
        }

        private static void ReadDimention(XmlNode xmlNode, ISChemaDimention schemaDimentionExcel)
        {
            schemaDimentionExcel.Format = MigrationConstants.Default;
            foreach (XmlNode childNode in xmlNode.ChildNodes)
            {
                string var = childNode.Name;
                switch (var)
                {
                    case "Init":
                        if (childNode.Attributes != null)
                            foreach (XmlAttribute atrribute in childNode.Attributes)
                            {
                                switch (atrribute.Name)
                                {
                                    case "startwith":
                                        schemaDimentionExcel.StartWith = atrribute.Value;
                                        break;
                                    case "searchInit":
                                        schemaDimentionExcel.SearchInit = atrribute.Value;
                                        break;
                                    case "searchDeep":
                                        schemaDimentionExcel.SearchDeep = atrribute.Value;
                                        break;
                                    case "name":
                                        schemaDimentionExcel.Name = atrribute.Value;
                                        break;
                                }

                            }
                        break;
                    case "Table":
                        if (childNode.Attributes != null)
                            foreach (XmlAttribute attribute in childNode.Attributes)
                            {
                                switch (attribute.Name)
                                {
                                    case "name":
                                        schemaDimentionExcel.TableName = attribute.Value;
                                        break;
                                    case "srchname":
                                        schemaDimentionExcel.SrchName = attribute.Value;
                                        break;
                                    case "source":
                                        schemaDimentionExcel.Source = attribute.Value;
                                        break;
                                    case "format":
                                        switch (attribute.Value)
                                        {
                                            case MigrationConstants.Time:
                                                schemaDimentionExcel.Format = MigrationConstants.Time;
                                                break;
                                            default:
                                                schemaDimentionExcel.Format = MigrationConstants.Default;
                                                break;
                                        }
                                        
                                        break;
                                }

                            }
                        break;
                    case "Replace":
                        if (childNode.Attributes != null)
                            if (childNode.Attributes["startvalue"] != null && childNode.Attributes["endvalue"] != null)
                            {
                                if(!schemaDimentionExcel.Replace.ContainsKey(childNode.Attributes["startvalue"]))
                                    schemaDimentionExcel.Replace.Add(childNode.Attributes["startvalue"].Value.ToLower(), childNode.Attributes["endvalue"].Value.ToLower());
                            }
                        break;
                }
               
            }
        }

        
    }
}
